#pragma once

#include <memory>
#include <stdarg.h>
#include <functional>

class ILog
{
public:
	virtual void WriteStdErr(const wchar_t* fmt, ...) = 0;
	virtual void WriteVStdErr(const wchar_t* fmt, va_list argptr) = 0;

	virtual void WriteStdErrLine(const wchar_t* fmt, ...) = 0;
	virtual void WriteVStdErrLine(const wchar_t* fmt, va_list argptr) = 0;

	virtual void WriteStdOut(const wchar_t* fmt, ...) = 0;

	virtual void WriteStdOutLine(const wchar_t* fmt, ...) = 0;
	virtual void WriteVStdOutLine(const wchar_t* fmt, va_list argptr) = 0;
	virtual bool IsInfoEnabled(int level) const = 0;
	virtual void WriteInfo(int level, const wchar_t* fmt, ...) = 0;
	virtual void WriteInfoString(int level, const wchar_t* fmt) = 0;

	inline void WriteInfoString(int level, const std::wstring& str)
	{
		this->WriteInfoString(level, str.c_str());
	}

	static inline void argptrConv(std::function<void(const wchar_t*, va_list)> funcPrintf, const wchar_t* fmt, ...)
	{
		va_list argptr;
		va_start(argptr, fmt);
		funcPrintf(fmt, argptr);
		va_end(argptr);
	}

};

class CConsoleLog : public ILog
{
public:
	static std::shared_ptr<ILog> CreateInstance();

	virtual void WriteStdErr(const wchar_t* fmt, ...);
	virtual void WriteVStdErr(const wchar_t* fmt, va_list argptr);
	virtual void WriteStdErrLine(const wchar_t* fmt, ...);
	virtual void WriteVStdErrLine(const wchar_t* fmt, va_list argptr);
	virtual void WriteStdOut(const wchar_t* fmt, ...);
	virtual void WriteStdOutLine(const wchar_t* fmt, ...);
	virtual void WriteVStdOutLine(const wchar_t* fmt, va_list argptr);
	virtual bool IsInfoEnabled(int level) const;
	virtual void WriteInfo(int level, const wchar_t* fmt, ...);
	virtual void WriteInfoString(int level, const wchar_t* fmt);
protected:
	void Write(FILE* fp, const wchar_t* fmt, va_list argptr);
	void WriteString(FILE* fp, const wchar_t* s);
};